﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AMail.Common;
using AMail.Common.Interfaces.Data;
using AMail.Modules.Messages.Models;
using Microsoft.Practices.Composite.Events;
using AMail.Common.Events;
using Elentok.Common.Wpf;
using System.Windows.Input;
using Elentok.Common.Wpf.Dialogs;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Windows;
using Microsoft.Win32;
using System.IO;
using System.Diagnostics;

namespace AMail.Modules.Messages.ViewModels
{
  public class MessageViewModel : ViewModelBase, IMessageViewModel
  {
    private IMailMessage message;

    #region IMessageViewModel Members

    /// <summary>
    /// Gets or sets the message
    /// </summary>
    public IMailMessage Message
    {
      get
      {
        return this.message;
      }
      set
      {
        if (this.message == value)
          return;

        this.message = value;
        OnPropertyChanged("Message");
        UpdateCommands();
      }
    }

    public DelegateCommand<IMailMessage> ChangeEncodingCommand { get; private set; }

    public DelegateCommand<IMailAttachment> SaveAttachmentCommand { get; private set; }
    public DelegateCommand<IMailAttachment> OpenAttachmentCommand { get; private set; }

    #endregion

    public MessageViewModel(IEventAggregator eventAggregator)
    {
      eventAggregator.GetEvent<SelectedMessagesChangedEvent>().Subscribe(OnSelectedMessagesChanged);

      this.ChangeEncodingCommand = new DelegateCommand<IMailMessage>(
        ExecuteChangeEncodingCommand,
        CanExecuteChangeEncodingCommand);

      this.SaveAttachmentCommand = new DelegateCommand<IMailAttachment>(
        ExecuteSaveAttachmentCommand, 
        CanExecuteSaveAttachmentCommand);

      this.OpenAttachmentCommand = new DelegateCommand<IMailAttachment>(ExecuteOpenAttachmentCommand);
    }

    private void OnSelectedMessagesChanged(IEnumerable<IMailMessage> selectedMessages)
    {
      if (selectedMessages.Count() != 1)
        this.Message = null;
      else
      {
        this.Message = selectedMessages.First();
      }
    }

    #region Change Encoding Command

    private void ExecuteChangeEncodingCommand(IMailMessage message)
    {
      SelectEncodingDialog dialog = new SelectEncodingDialog();
      if (dialog.ShowDialog() == true)
      {
        message.Encoding = dialog.ViewModel.SelectedEncoding;
      }
    }

    private bool CanExecuteChangeEncodingCommand(IMailMessage message)
    {
      return (message != null);
    }

    #endregion

    #region Save Attachment Command
    private void ExecuteSaveAttachmentCommand(IMailAttachment attachment)
    {
      SaveFileDialog dialog = new SaveFileDialog();
      dialog.FileName = attachment.Title;
      if (dialog.ShowDialog() == true)
      {
        File.WriteAllBytes(dialog.FileName, attachment.Data.ToArray());
        MessageBox.Show("Attachment saved successfuly to '" + dialog.FileName + "'");
      }
    }

    private bool CanExecuteSaveAttachmentCommand(IMailAttachment attachment)
    {
      return attachment != null;
    }
    #endregion

    private void TryDeleteFile(string filename)
    {
      while (true)
      {
        try
        {
          File.Delete(filename);
        }
        catch (IOException ex)
        {
          if (MessageBox.Show(ex.Message + "\r\n\r\nTry again?",
            "Error deleting the temporary file",
            MessageBoxButton.YesNo) == MessageBoxResult.No)
          {
            return;
          }
        }
        return;
      }
      
    }

    private void ExecuteOpenAttachmentCommand(IMailAttachment attachment)
    {
      string path = Path.GetTempPath();
      if (!string.IsNullOrEmpty(attachment.Title))
        path = Path.Combine(path, attachment.Title);
      else
        path = Path.Combine(path, "Untitled");

      File.WriteAllBytes(path, attachment.Data.ToArray());

      Process.Start(path);

      MessageBox.Show("Press OK to delete the temporary file");

      TryDeleteFile(path);
    }

    private void UpdateCommands()
    {
      this.ChangeEncodingCommand.RaiseCanExecuteChanged();
    }
  }
}
